package jp.syuriken.snsw.terenaibot;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import java.util.Properties;

/**
 * データを読み書きするためのユーティリティ。
 * 
 * <p>
 * このクラスは直接使用するのではなく、 {@link DataProviderFactory#getProvider(String)}を使用してインスタンスを取得するべきです。
 * 終了するときもファイルの保管が自動的に行われ、同じファイルを開くときも直近のインスタンスが再利用されます。また、保管を強制的に行いたいのであれば {@link #store()} を使用して下さい。
 * </p>
 * @author $Author: snswinhaiku.lo@gmail.com $
 */
public class DataProvider {
	
	/** データを格納する */
	protected Properties dataProperties;
	
	/** データファイル名 */
	protected String dataFile;
	

	/**
	 * インスタンスを生成する。
	 * 
	 * @param dataFile データファイル
	 */
	public DataProvider(String dataFile) {
		this.dataFile = dataFile;
		dataProperties = new Properties();
		Reader dataReader = null;
		try {
			dataReader = new FileReader(dataFile);
			dataProperties.load(dataReader);
		} catch (FileNotFoundException e) {
			// do nothing
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (dataReader != null) {
				try {
					dataReader.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
	
	/**
	 * キーが格納されているかどうかチェックする
	 * 
	 * @param key キー
	 * @return 格納されているかどうか
	 */
	public boolean containKey(String key) {
		return dataProperties.containsKey(key);
	}
	
	@Override
	protected void finalize() throws Throwable {
		store();
		super.finalize();
	}
	
	/**
	 * 実際のデータファイル名を取得する。
	 * @return 保管に使用されるデータファイル名
	 */
	public String getFileName() {
		return dataFile;
	}
	
	/**
	 * キーに関連付けられたデータを取得する。キーが存在しない場合nullが返ります。
	 * 
	 * @param key キー
	 * @return 関連付けられたデータ
	 */
	public String getString(String key) {
		return dataProperties.getProperty(key);
	}
	
	/**
	 * キーに関連付けられたデータを取得する。キーが存在しない場合デフォルト値を使用します。
	 * 
	 * @param key キー
	 * @param defaultValue デフォルト値
	 * @return 関連付けられたデータ。存在しない場合デフォルト値
	 */
	public String getString(String key, String defaultValue) {
		return dataProperties.getProperty(key, defaultValue);
	}
	
	/**
	 * キーにデータを関連付ける。 
	 * 
	 * <p>{@link #store()}を使用することでデータが実際に保管されます。
	 * これは {@link DataProviderFactory} により半自動的に呼び出されますので、
	 * 本当にすぐに保管する必要がある時以外は {@link #store()} を使用しないで下さい。
	 * 
	 * @param key キー
	 * @param value 値
	 */
	public void setString(String key, String value) {
		dataProperties.setProperty(key, value);
	}
	
	/**
	 * データを保管する。 {@link DataProviderFactory}により半自動的に呼び出されます。
	 * @throws IOException 保管に失敗しました。
	 */
	public void store() throws IOException {
		Writer fileWriter = null;
		try {
			fileWriter = new FileWriter(dataFile);
			dataProperties.store(fileWriter, "Auto generated by jp.syuriken.snsw.terenaibot.DataProvider");
		} finally {
			try {
				if (fileWriter != null) {
					fileWriter.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
}
